home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / ncurses.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  16KB  |  658 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * [n]curses output.
  5.   *
  6.   * There are 17 color modes:
  7.   *  -H0/-H1 are black/white output
  8.   *  -H2 through -H16 give you different color allocation strategies. On my
  9.   *    system, -H14 seems to give nice results.
  10.   *
  11.   * Copyright 1997 Samuel Devulder, Bernd Schmidt
  12.   */
  13.  
  14. /****************************************************************************/
  15.  
  16. #include "sysconfig.h"
  17. #include "sysdeps.h"
  18.  
  19. #include <ctype.h>
  20. #include <signal.h>
  21.  
  22. /****************************************************************************/
  23.  
  24. #include "config.h"
  25. #include "options.h"
  26. #include "threaddep/penguin.h"
  27. #include "uae.h"
  28. #include "memory.h"
  29. #include "custom.h"
  30. #include "readcpu.h"
  31. #include "newcpu.h"
  32. #include "xwin.h"
  33. #include "keyboard.h"
  34. #include "keybuf.h"
  35. #include "disk.h"
  36. #include "debug.h"
  37. #include "gui.h"
  38.  
  39. #ifdef HAVE_NCURSES_H
  40. #include <ncurses.h>
  41. #else
  42. #include <curses.h>
  43. #endif
  44.  
  45. /****************************************************************************/
  46.  
  47. #define MAXGRAYCHAR 128
  48.  
  49. enum {
  50.     MYCOLOR_BLACK, MYCOLOR_RED, MYCOLOR_GREEN, MYCOLOR_BLUE,
  51.     MYCOLOR_YELLOW, MYCOLOR_CYAN, MYCOLOR_MAGENTA, MYCOLOR_WHITE
  52. };
  53.  
  54. static int mycolor2curses_map [] = {
  55.     COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_BLUE,
  56.     COLOR_YELLOW, COLOR_CYAN, COLOR_MAGENTA, COLOR_WHITE
  57. };
  58.  
  59. static int mycolor2pair_map[] = { 1,2,3,4,5,6,7,8 };
  60.  
  61. static chtype graychar[MAXGRAYCHAR];
  62. static int maxc,max_graychar;
  63. static int curses_on;
  64.  
  65. static int *x2graymap;
  66.  
  67. /* Keyboard and mouse */
  68.  
  69. static int keystate[256];
  70. static int keydelay = 20;
  71.  
  72. static void curses_exit(void);
  73.  
  74. /****************************************************************************/
  75.  
  76. static RETSIGTYPE sigbrkhandler(int foo)
  77. {
  78.     curses_exit();
  79.     activate_debugger();
  80. }
  81.  
  82. void setup_brkhandler(void)
  83. {
  84.     struct sigaction sa;
  85.     sa.sa_handler = sigbrkhandler;
  86.     sa.sa_flags = 0;
  87.     sa.sa_flags = SA_RESTART;
  88.     sigemptyset(&sa.sa_mask);
  89.     sigaction(SIGINT, &sa, NULL);
  90. }
  91.  
  92. /***************************************************************************/
  93.  
  94. static void curses_insert_disk(void)
  95. {
  96.     curses_exit();
  97.     gui_changesettings();
  98.     flush_screen(0,0);
  99. }
  100.  
  101. /****************************************************************************/
  102.  
  103. /*
  104.  * old:    fmt = " .,:=(Io^vM^vb*X^#M^vX*boI(=:. ^b^vobX^#M" doesn't work: "^vXb*oI(=:. ";
  105.  * good:    fmt = " .':;=(IoJpgFPEB#^vgpJoI(=;:'. ^v^b=(IoJpgFPEB";
  106.  *
  107.  *     fmt = " .,:=(Io*b^vM^vX^#M^vXb*oI(=:. ";
  108.  */
  109.  
  110. static void init_graychar(void)
  111. {
  112.     chtype *p = graychar;
  113.     chtype attrs;
  114.     int i,j;
  115.     char *fmt;
  116.  
  117.     attrs = termattrs();
  118.     if ((currprefs.color_mode & 1) == 0 && (attrs & (A_REVERSE | A_BOLD)))
  119.     fmt = " .':;=(IoJpgFPEB#^vgpJoI(=;:'. ^v^boJpgFPEB";
  120.     else if ((currprefs.color_mode & 1) == 0 && (attrs & A_REVERSE))
  121.     fmt = " .':;=(IoJpgFPEB#^vgpJoI(=;:'. ";
  122.     else
  123.     /* One could find a better pattern.. */
  124.     fmt = " .`'^^\",:;i!1Il+=tfjxznuvyZYXHUOQ0MWB";
  125.     attrs = A_NORMAL | COLOR_PAIR (0);
  126.     while(*fmt) {
  127.     if(*fmt == '^') {
  128.         ++fmt;
  129.         switch(*fmt) {
  130.         case 's': case 'S': attrs ^= A_STANDOUT; break;
  131.         case 'v': case 'V': attrs ^= A_REVERSE; break;
  132.         case 'b': case 'B': attrs ^= A_BOLD; break;
  133.         case 'd': case 'D': attrs ^= A_DIM; break;
  134.         case 'u': case 'U': attrs ^= A_UNDERLINE; break;
  135.         case 'p': case 'P': attrs  = A_NORMAL; break;
  136.         case '#': if(ACS_CKBOARD == ':')
  137.                    *p++ = (attrs | '#');
  138.               else *p++ = (attrs | ACS_CKBOARD); break;
  139.         default:  *p++ = (attrs | *fmt); break;
  140.         }
  141.         ++fmt;
  142.     } else *p++ = (attrs | *fmt++);
  143.     if(p >= graychar + MAXGRAYCHAR) break;
  144.     }
  145.     max_graychar = (p - graychar) - 1;
  146.  
  147.     for (i = 0; i <= maxc; i++)
  148.     x2graymap[i] = i * max_graychar / maxc;
  149. #if 0
  150.     for(j=0;j<LINES;++j) {
  151.     move(j,0);
  152.     for(i=0;i<COLS;++i) addch(graychar[i % (max_graychar+1)]);
  153.     }
  154.     refresh();
  155.     sleep(3);
  156. #endif
  157. }
  158.  
  159. static int x_map[900], y_map[700], y_rev_map [700];
  160.  
  161.  
  162. /****************************************************************************/
  163.  
  164. static void init_colors(void)
  165. {
  166.     int i;
  167.  
  168.     maxc = 0;
  169.  
  170.     for(i = 0; i < 4096; ++i) {
  171.     int r,g,b,r1,g1,b1;
  172.     int m, comp;
  173.     int ctype;
  174.  
  175.     r =  i >> 8;
  176.     g = (i >> 4) & 15;
  177.     b =  i & 15;
  178.  
  179.     xcolors[i] = (77 * r + 151 * g + 28 * b)/16;
  180.     if(xcolors[i] > maxc)
  181.         maxc = xcolors[i];
  182.     m = r;
  183.     if (g > m)
  184.         m = g;
  185.     if (b > m)
  186.         m = b;
  187.     if (m == 0) {
  188.         xcolors[i] |= MYCOLOR_WHITE << 8; /* to get gray instead of black in dark areas */
  189.         continue;
  190.     }
  191.  
  192.     if ((currprefs.color_mode & ~1) != 0) {
  193.         r1 = r*15 / m;
  194.         g1 = g*15 / m;
  195.         b1 = b*15 / m;
  196.  
  197.         comp = 8;
  198.         for (;;) {
  199.         if (b1 < comp) {
  200.             if (r1 < comp)
  201.             ctype = MYCOLOR_GREEN;
  202.             else if (g1 < comp)
  203.             ctype = MYCOLOR_RED;
  204.             else
  205.             ctype = MYCOLOR_YELLOW;
  206.         } else {
  207.             if (r1 < comp) {
  208.             if (g1 < comp)
  209.                 ctype = MYCOLOR_BLUE;
  210.             else
  211.                 ctype = MYCOLOR_CYAN;
  212.             } else if (g1 < comp)
  213.                 ctype = MYCOLOR_MAGENTA;
  214.             else {
  215.             comp += 4;
  216.             if (comp == 12 && (currprefs.color_mode & 2) != 0)
  217.                 continue;
  218.             ctype = MYCOLOR_WHITE;
  219.             }
  220.         }
  221.         break;
  222.         }
  223.         if (currprefs.color_mode & 8) {
  224.         if (ctype == MYCOLOR_BLUE && xcolors[i] > /*27*/50)
  225.             ctype = r1 > (g1+2) ? MYCOLOR_MAGENTA : MYCOLOR_CYAN;
  226.         if (ctype == MYCOLOR_RED && xcolors[i] > /*75*/ 90)
  227.             ctype = b1 > (g1+6) ? MYCOLOR_MAGENTA : MYCOLOR_YELLOW;
  228.         }
  229.         xcolors[i] |= ctype << 8;
  230.     }
  231.     }
  232.     if (currprefs.color_mode & 4) {
  233.     int j;
  234.     for (j = MYCOLOR_RED; j < MYCOLOR_WHITE; j++) {
  235.         int best = 0, maxv = 0;
  236.         int multi, divi;
  237.  
  238.         for (i = 0; i < 4096; i++)
  239.         if ((xcolors[i] & 255) > maxv && (xcolors[i] >> 8) == j) {
  240.             best = i;
  241.             maxv = (xcolors[best] & 255);
  242.         }
  243.         /* Now maxv is the highest intensity a color of type J is supposed to have.
  244.          * In  reality, it will most likely only have intensity maxv*multi/divi.
  245.          * We try to correct this. */
  246.         maxv = maxv * 256 / maxc;
  247.  
  248.         divi = 256;
  249.         switch (j) {
  250.          case MYCOLOR_RED:     multi = 77; break;
  251.          case MYCOLOR_GREEN:   multi = 151; break;
  252.          case MYCOLOR_BLUE:    multi = 28; break;
  253.          case MYCOLOR_YELLOW:  multi = 228; break;
  254.          case MYCOLOR_CYAN:    multi = 179; break;
  255.          case MYCOLOR_MAGENTA: multi = 105; break;
  256.          default: abort();
  257.         }
  258. #if 1 /* This makes the correction less extreme */
  259.         if (! (currprefs.color_mode & 8))
  260.         multi = (multi + maxv) / 2;
  261. #endif
  262.         for (i = 0; i < 4096; i++) {
  263.         int v = xcolors[i];
  264.         if ((v >> 8) != j)
  265.             continue;
  266.         v &= 255;
  267.         /* I don't think either of these is completely correct, but
  268.          * the first one produces rather good results. */
  269. #if 1
  270.         v = v * divi / multi;
  271.         if (v > maxc)
  272.             v = maxc;
  273. #else
  274.         v = v * 256 / maxv);
  275.         if (v > maxc)
  276.             /*maxc = v*/abort();
  277. #endif
  278.         xcolors[i] = v | (j << 8);
  279.         }
  280.     }
  281.     }
  282.     x2graymap = (int *)malloc(sizeof(int) * (maxc+1));
  283. }
  284.  
  285. static void curses_init(void)
  286. {
  287.     initscr ();
  288.  
  289.     start_color ();
  290.     if (! has_colors () || COLOR_PAIRS < 20 /* whatever */)
  291.     currprefs.color_mode &= 1;
  292.     else {
  293.     init_pair (1, COLOR_BLACK, COLOR_BLACK);
  294.     init_pair (2, COLOR_RED, COLOR_BLACK);
  295.     init_pair (3, COLOR_GREEN, COLOR_BLACK);
  296.     init_pair (4, COLOR_BLUE, COLOR_BLACK);
  297.     init_pair (5, COLOR_YELLOW, COLOR_BLACK);
  298.     init_pair (6, COLOR_CYAN, COLOR_BLACK);
  299.     init_pair (7, COLOR_MAGENTA, COLOR_BLACK);
  300.     init_pair (8, COLOR_WHITE, COLOR_BLACK);
  301.     }
  302.     printf ("curses_init: %d pairs available\n", COLOR_PAIRS);
  303.  
  304.     cbreak(); noecho();
  305.     nonl (); intrflush(stdscr, FALSE); keypad(stdscr, TRUE);
  306.     nodelay(stdscr, TRUE);
  307.     leaveok(stdscr, TRUE);
  308.  
  309.     attron (A_NORMAL | COLOR_PAIR (0));
  310.     bkgd(' '|COLOR_PAIR(0));
  311.  
  312. #ifdef NCURSES_MOUSE_VERSION
  313.     mousemask(BUTTON1_PRESSED | BUTTON1_RELEASED |
  314.           BUTTON2_PRESSED | BUTTON2_RELEASED |
  315.           BUTTON3_PRESSED | BUTTON3_RELEASED |
  316.           REPORT_MOUSE_POSITION, NULL);
  317. #endif
  318.  
  319.     init_graychar();
  320.     curses_on = 1;
  321. }
  322.  
  323. static void curses_exit(void)
  324. {
  325. #ifdef NCURSES_MOUSE_VERSION
  326.     mousemask(0, NULL);
  327. #endif
  328.  
  329.     nocbreak(); echo(); nl(); intrflush(stdscr, TRUE);
  330.     keypad(stdscr, FALSE); nodelay(stdscr, FALSE); leaveok(stdscr, FALSE);
  331.     endwin();
  332.     curses_on = 0;
  333. }
  334.  
  335. /****************************************************************************/
  336.  
  337. static int getgraycol(int x, int y)
  338. {
  339.     uae_u8 *bufpt;
  340.     int xs, xl, ys, yl, c, cm;
  341.  
  342.     xl = x_map[x+1] - (xs = x_map[x]);
  343.     yl = y_map[y+1] - (ys = y_map[y]);
  344.  
  345.     bufpt = ((uae_u8 *)gfxvidinfo.bufmem) + ys*currprefs.gfx_width + xs;
  346.  
  347.     cm = c = 0;
  348.     for(y = 0; y < yl; y++, bufpt += currprefs.gfx_width)
  349.     for(x = 0; x < xl; x++) {
  350.         c += bufpt[x];
  351.         ++cm;
  352.     }
  353.     if (cm)
  354.     c /= cm;
  355.     if (!currprefs.no_xhair)
  356.     c = maxc - c;
  357.     return graychar[x2graymap[c]];
  358. }
  359.  
  360. static int getcol(int x, int y)
  361. {
  362.     uae_u16 *bufpt;
  363.     int xs, xl, ys, yl, c, cm;
  364.     int bestcol = MYCOLOR_BLACK, bestccnt = 0;
  365.     unsigned char colcnt [8];
  366.  
  367.     memset (colcnt, 0 , sizeof colcnt);
  368.  
  369.     xl = x_map[x+1] - (xs = x_map[x]);
  370.     yl = y_map[y+1] - (ys = y_map[y]);
  371.  
  372.     bufpt = ((uae_u16 *)gfxvidinfo.bufmem) + ys*currprefs.gfx_width + xs;
  373.  
  374.     cm = c = 0;
  375.     for(y = 0; y < yl; y++, bufpt += currprefs.gfx_width)
  376.     for(x = 0; x < xl; x++) {
  377.         int v = bufpt[x];
  378.         int cnt;
  379.  
  380.         c += v & 0xFF;
  381.         cnt = ++colcnt[v >> 8];
  382.         if (cnt > bestccnt) {
  383.         bestccnt = cnt;
  384.         bestcol = v >> 8;
  385.         }
  386.         ++cm;
  387.     }
  388.     if (cm)
  389.     c /= cm;
  390.     if (!currprefs.no_xhair)
  391.     c = maxc - c;
  392.     return (graychar[x2graymap[c]] & ~A_COLOR) | COLOR_PAIR (mycolor2pair_map[bestcol]);
  393. }
  394.  
  395. static void flush_line_txt(int y)
  396. {
  397.     int x;
  398.     move (y,0);
  399.     if (currprefs.color_mode < 2)
  400.     for (x = 0; x < COLS; ++x) {
  401.         int c;
  402.  
  403.         c = getgraycol(x,y);
  404.         addch(c);
  405.     }
  406.     else
  407.     for (x = 0; x < COLS; ++x) {
  408.         int c;
  409.  
  410.         c = getcol(x,y);
  411.         addch(c);
  412.     }
  413. }
  414.  
  415. __inline__ void flush_line(int y)
  416. {
  417.     if(y < 0 || y >= currprefs.gfx_height) {
  418. /*       printf("flush_line out of window: %d\n", y); */
  419.        return;
  420.     }
  421.     if(!curses_on)
  422.     return;
  423.     flush_line_txt(y_rev_map[y]);
  424. }
  425.  
  426. void flush_block (int ystart, int ystop)
  427. {
  428.     int y;
  429.     if(!curses_on)
  430.     return;
  431.     ystart = y_rev_map[ystart];
  432.     ystop  = y_rev_map[ystop];
  433.     for(y = ystart; y <= ystop; ++y)
  434.     flush_line_txt(y);
  435. }
  436.  
  437. void flush_screen (int ystart, int ystop)
  438. {
  439.     if(!debugging && !curses_on) {
  440.     curses_init();
  441.     flush_block(0, currprefs.gfx_height - 1);
  442.     }
  443.     refresh();
  444. }
  445.  
  446. /****************************************************************************/
  447.  
  448. struct bstring *video_mode_menu = NULL;
  449.  
  450. void vidmode_menu_selected(int a)
  451. {
  452. }
  453.  
  454. int graphics_setup(void)
  455. {
  456.     return 1;
  457. }
  458.  
  459. int graphics_init(void)
  460. {
  461.     int i;
  462.  
  463.     if (currprefs.color_mode > 16)
  464.     fprintf(stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0;
  465.  
  466.     init_colors();
  467.  
  468.     curses_init();
  469.     fprintf(stderr,"Using %s.\n",longname());
  470.  
  471.     if (debugging)
  472.     curses_exit ();
  473.  
  474.     /* we have a 320x256x8 pseudo screen */
  475.  
  476.     currprefs.gfx_width = 320;
  477.     currprefs.gfx_height = 256;
  478.     currprefs.gfx_lores = 1;
  479.  
  480.     gfxvidinfo.width = currprefs.gfx_width;
  481.     gfxvidinfo.height = currprefs.gfx_height;
  482.     gfxvidinfo.maxblocklines = 1000;
  483.     gfxvidinfo.pixbytes = currprefs.color_mode < 2 ? 1 : 2;
  484.     gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * currprefs.gfx_width;
  485.     gfxvidinfo.bufmem = (char *)calloc(gfxvidinfo.rowbytes, currprefs.gfx_height+1);
  486.     gfxvidinfo.linemem = 0;
  487.     gfxvidinfo.can_double = 0;
  488.     switch (gfxvidinfo.pixbytes) {
  489.      case 1:
  490.     for (i = 0; i < 4096; i++)
  491.         xcolors[i] = xcolors[i] * 0x01010101;
  492.     gfxvidinfo.can_double = 1;
  493.     break;
  494.      case 2:
  495.     for (i = 0; i < 4096; i++)
  496.         xcolors[i] = xcolors[i] * 0x00010001;
  497.     gfxvidinfo.can_double = 1;
  498.     break;
  499.     }
  500.     if(!gfxvidinfo.bufmem) {
  501.     fprintf(stderr,"Not enough memory.\n");
  502.     return 0;
  503.     }
  504.  
  505.     for (i = 0; i < sizeof x_map / sizeof *x_map; i++)
  506.     x_map[i] = (i * currprefs.gfx_width) / COLS;
  507.     for (i = 0; i < sizeof y_map / sizeof *y_map; i++)
  508.     y_map[i] = (i * currprefs.gfx_height) / LINES;
  509.     for (i = 0; i < sizeof y_map / sizeof *y_map - 1; i++) {
  510.     int l1 = y_map[i];
  511.     int l2 = y_map[i+1];
  512.     int j;
  513.     if (l2 >= sizeof y_rev_map / sizeof *y_rev_map)
  514.         break;
  515.     for (j = l1; j < l2; j++)
  516.         y_rev_map[j] = i;
  517.     }
  518.  
  519.     buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
  520.     for(i=0; i<256; i++)
  521.     keystate[i] = 0;
  522.  
  523.     lastmx = lastmy = 0;
  524.     newmousecounters = 0;
  525.  
  526.     return 1;
  527. }
  528.  
  529. /****************************************************************************/
  530.  
  531. void graphics_leave(void)
  532. {
  533.     curses_exit();
  534. }
  535.  
  536. /****************************************************************************/
  537.  
  538. static int keycode2amiga(int ch)
  539. {
  540.     switch(ch) {
  541.     case KEY_A1:    return AK_NP7;
  542.     case KEY_UP:    return AK_NP8;
  543.     case KEY_A3:    return AK_NP9;
  544.     case KEY_LEFT:  return AK_NP4;
  545.     case KEY_B2:    return AK_NP5;
  546.     case KEY_RIGHT: return AK_NP6;
  547.     case KEY_C1:    return AK_NP1;
  548.     case KEY_DOWN:  return AK_NP2;
  549.     case KEY_C3:    return AK_NP3;
  550.     case KEY_ENTER: return AK_ENT;
  551.     case 13:        return AK_RET;
  552.     case ' ':       return AK_SPC;
  553.     case 27:        return AK_ESC;
  554.     default: return -1;
  555.     }
  556. }
  557.  
  558. /***************************************************************************/
  559.  
  560. void handle_events(void)
  561. {
  562.     int ch;
  563.     int kc;
  564.  
  565.     /* Hack to simulate key release */
  566.     for(kc = 0; kc < 256; ++kc) {
  567.     if(keystate[kc]) if(!--keystate[kc]) record_key((kc << 1) | 1);
  568.     }
  569.     if(buttonstate[0]) --buttonstate[0];
  570.     if(buttonstate[1]) --buttonstate[1];
  571.     if(buttonstate[2]) --buttonstate[2];
  572.  
  573.     newmousecounters = 0;
  574.     if(!curses_on) return;
  575.  
  576.     while((ch = getch())!=ERR) {
  577.     if(ch == 12) {clearok(stdscr,TRUE);refresh();}
  578. #ifdef NCURSES_MOUSE_VERSION
  579.     if(ch == KEY_MOUSE) {
  580.         MEVENT ev;
  581.         if(getmouse(&ev) == OK) {
  582.         lastmx = (ev.x*currprefs.gfx_width)/COLS;
  583.         lastmy = (ev.y*currprefs.gfx_height)/LINES;
  584.         if(ev.bstate & BUTTON1_PRESSED)  buttonstate[0] = keydelay;
  585.         if(ev.bstate & BUTTON1_RELEASED) buttonstate[0] = 0;
  586.         if(ev.bstate & BUTTON2_PRESSED)  buttonstate[1] = keydelay;
  587.         if(ev.bstate & BUTTON2_RELEASED) buttonstate[1] = 0;
  588.         if(ev.bstate & BUTTON3_PRESSED)  buttonstate[2] = keydelay;
  589.         if(ev.bstate & BUTTON3_RELEASED) buttonstate[2] = 0;
  590.         }
  591.     }
  592. #endif
  593.     if (ch == 6)  ++lastmx; /* ^F */
  594.     if (ch == 2)  --lastmx; /* ^B */
  595.     if (ch == 14) ++lastmy; /* ^N */
  596.     if (ch == 16) --lastmy; /* ^P */
  597.     if (ch == 11) {buttonstate[0] = keydelay;ch = 0;} /* ^K */
  598.     if (ch == 25) {buttonstate[2] = keydelay;ch = 0;} /* ^Y */
  599.     if (ch == 15) uae_reset (); /* ^O */
  600.     if (ch == 17) uae_quit (); /* ^Q */
  601.     if (ch == KEY_F(1)) {
  602.       curses_insert_disk();
  603.       ch = 0;
  604.     }
  605.  
  606.     if(isupper(ch)) {
  607.         keystate[AK_LSH] =
  608.         keystate[AK_RSH] = keydelay;
  609.         record_key(AK_LSH << 1);
  610.         record_key(AK_RSH << 1);
  611.         kc = keycode2amiga(tolower(ch));
  612.         keystate[kc] = keydelay;
  613.         record_key(kc << 1);
  614.     } else if((kc = keycode2amiga(ch)) >= 0) {
  615.         keystate[kc] = keydelay;
  616.         record_key(kc << 1);
  617.     }
  618.     }
  619.     gui_handle_events();
  620. }
  621.  
  622. /***************************************************************************/
  623.  
  624. void target_specific_usage(void)
  625. {
  626.     printf("----------------------------------------------------------------------------\n");
  627.     printf("[n]curses specific usage:\n");
  628.     printf("  -x : Display reverse video.\n");
  629.     printf("By default uae will assume a black on white display. If yours\n");
  630.     printf("is light on dark, use -x. In case of graphics garbage, ^L will\n");
  631.     printf("redisplay the screen. ^K simulate left mouse button, ^Y RMB.\n");
  632.     printf("If you are using a xterm UAE can use the mouse. Else use ^F ^B\n");
  633.     printf("^P ^N to emulate mouse mouvements.\n");
  634.     printf("----------------------------------------------------------------------------\n");
  635. }
  636.  
  637. /***************************************************************************/
  638.  
  639. int debuggable(void)
  640. {
  641.     return 1;
  642. }
  643.  
  644. int needmousehack(void)
  645. {
  646.     return 1;
  647. }
  648.  
  649. void LED(int on)
  650. {
  651. }
  652.  
  653. void write_log (const char *buf)
  654. {
  655.  
  656. }
  657.  
  658.